//index.js
//获取应用实例
const app = getApp()
const util = require("../../utils/util");
const gbk = require("../../utils/gbkUtil/gbkUtil");
var that; //把this对象复制到临时变量that
import Notify from '@vant/weapp/notify/notify';
Page({
    data: {
        show: false, //加载动画的显示
        status: "未连接",
        msg: "BLEHID",
        deviceId: "",
        connectedDeviceId: "", //已连接设备uuid
        deviceName: "ble2usbhid",
        ServicweId: '', // 服务uuid
        writeCharacteristicsId: "", // 服务的特征值uuid
        textValue: '', // 输入的文字
        Alist: [98, 89, 90, 91, 92, 93, 94, 95, 96, 97], // 转换成对应的HID键盘编码 分别代表 0 ~ 9         
        notify_duration: 1580,  // 通知消息的持续时间 ms
    },
    //事件处理函数
    bindViewTap: function () {
        wx.navigateTo({
            url: '../logs/logs'
        })
    },

    // 离开此页面的时候执行此方法，关闭连接
    onUnload: function () {
        // TODO 这个方法是不是写错了，应该是that.closeConnect()
        that.closeConnect();
        that.closeBluetoothAdapter();
    },
    onLoad: function () {
        that = this;
        that.setData({
            show: false
        })
        if (wx.openBluetoothAdapter) {
            that.setData({
                msg: "...."
            })
            // 1、初始化蓝牙模块。
            wx.openBluetoothAdapter({
                success: function (res) {
                    /* 获取本机的蓝牙状态 */
                    that.getBluetoothAdapterState();
                    that.setData({
                        msg: "getBluetoothAdapterState"
                    })
                },
                fail: function (err) {
                    // 
                    that.setData({
                        msg: "初始化失败！",
                    })

                }
            })
        } else {}
    },

    // 2、获取本机蓝牙适配器状态
    getBluetoothAdapterState: function () {

        wx.getBluetoothAdapterState({
            success: function (res) {
                that.startBluetoothDevicesDiscovery()
                that.setData({
                    msg: "开始搜索蓝牙...",
                })
            },
            fail(res) {
                console.log(res)
            }
        })
    },

    // 3、关闭蓝牙连接，并且 开始搜寻附近的蓝牙外围设备。
    startBluetoothDevicesDiscovery: function () {
        that.setData({
            show: true
        })
        // 防止用户点错，在已连接的情况下再次点击,所以打开蓝牙适配器
        wx.openBluetoothAdapter({});
        that.closeConnect();
        that.setData({
            devices: {}
        })
        setTimeout(() => {
            wx.startBluetoothDevicesDiscovery({
                success: function (res) {
                    /* 获取蓝牙设备列表 */
                    that.setData({
                        msg: "蓝牙搜索完毕！",
                    })
                    that.getBluetoothDevices();
                },
                fail(res) {
                    that.setData({
                        msg: "搜索失败，请打开蓝牙后重试！",
                    })
                    setTimeout(() => {
                        // 关闭加载动画
                        that.setData({
                            show: false
                        })
                    }, 500);

                }
            })
        }, 500)
    },

    /**4、获取在蓝牙模块生效期间所有搜索到的蓝牙设备。
     * 包括已经和本机处于连接状态的设备。
     *  */
    getBluetoothDevices: function () {

        setTimeout(() => {
            wx.getBluetoothDevices({
                services: [],
                allowDuplicatesKey: false,
                interval: 0,
                success: function (res) {
                    console.log("res.devices:", JSON.stringify(res.devices));
                    that.setData({
                        devices: res.devices,
                    })

                    if (res.devices.length > 0) {
                        console.log("devices列表:", res.devices);
                        let i;
                        for (i = 0; i < res.devices.length; i++) {
                            // console.log(res.devices[i].name);
                            if ('ble2usbhid' === res.devices[i].name) {
                                /* 根据指定的蓝牙设备名称匹配到deviceId */
                                that.deviceId = res.devices[i].deviceId,
                                    that.setData({
                                        status: "正在连接" + that.deviceId,
                                        msg: "已找到设备 正在连接！",
                                    })


                                //停止搜寻附近的蓝牙外围设备。
                                wx.stopBluetoothDevicesDiscovery({
                                    success: function (res) {
                                        console.log(res, '已停止搜索')
                                    },
                                    fail(res) {
                                        console.log(res, '停止搜索失败')
                                    }
                                })
                                that.connectTO();
                                break;
                            };
                        };
                        if (res.devices.length == i) {
                            setTimeout(() => {
                                that.setData({
                                    msg: "未找到设备，请拔插USB后重试！",
                                    show: false
                                })
                            }, 50)
                        }

                    } else {}
                },
                fail(res) {
                    console.log(res, '获取蓝牙设备列表失败=====')
                    setTimeout(() => {
                        that.setData({
                            msg: "蓝牙搜索失败请重试！",
                            show: false
                        })
                    }, 50)
                }
            })
        }, 50)
    },

    // 5、连接蓝牙
    connectTO: function () {
        wx.createBLEConnection({
            deviceId: that.deviceId,
            success: function (res) {
                that.connectedDeviceId = that.deviceId;
                that.setData({
                    connectedDeviceId: that.deviceId,
                    devices: null,
                    status: "已连接" + that.deviceId,
                    msg: "蓝牙服务已准备！",
                })
                // 设置微信小程序发送最大的MTU 区间在（22,152）之间，需要和接受设备那边去协商，根据商家提供的说法是32个字节以内。为了防止边界值无效化，选择31字节
                // wx.setBLEMTU({
                //   deviceId: that.deviceI,
                //   mtu: 31,
                // })
                /* 获取连接设备的service服务 */
                that.getBLEDeviceServices();
            },
            fail: function (res) {
                that.setData({
                    status: "连接失败",
                    msg: "连接失败！请重试",
                    show: false
                })
                console.log(res, "连接失败")
            },
            complete: function () {}

        })
    },
    // 6、获取蓝牙低功耗设备所有服务 (service)。并且选出 FFE0 服务
    getBLEDeviceServices: function () {
        setTimeout(() => {
            wx.getBLEDeviceServices({
                deviceId: that.connectedDeviceId,
                success: function (res) {
                    that.setData({
                        msg: "蓝牙服务开启中"
                    })

                    console.log(JSON.stringify(res.services))

                    for (let i = 0; i < res.services.length; i++) {

                        if (res.services[i].uuid.indexOf("FFE0") >= 0) {
                            that.setData({
                                msg: "蓝牙服务已就绪"
                            })

                            that.services = res.services[i]
                            /* 获取连接设备的所有特征值 */
                            that.getBLEDeviceCharacteristics()
                            break;
                        }
                    }
                },
                fail: (res) => {
                    console.log(res)
                    that.setData({
                        msg: "服务搜索失败",
                        show: false
                    })
                }
            })
        }, 500)
    },

    // 7、获取蓝牙低功耗设备某个服务中所有特征 (characteristic)。
    getBLEDeviceCharacteristics: function () {
        console.log("find char of " + that.services.uuid)
        setTimeout(() => {
            wx.getBLEDeviceCharacteristics({
                deviceId: that.connectedDeviceId,
                serviceId: that.services.uuid,
                success: function (res) {
                    that.setData({
                        msg: "发现特征" + res.characteristics.length
                    })
                    console.log('蓝牙特征值UUID:', res.characteristics)
                    for (let i = 0; i < res.characteristics.length; i++) {
                        if (res.characteristics[i].properties.write && res.characteristics[i].uuid.indexOf('FFE3') >= 0) {
                            that.setData({
                                status: "蓝牙已连接",
                                msg: "蓝牙连接成功 可以发送文字",
                                show: false
                            })
                            /* 获取蓝牙特征值 */
                            that.ServicweId = that.services.uuid;
                            that.writeCharacteristicsId = res.characteristics[i].uuid
                            // 启用低功耗蓝牙设备特征值变化时的 notify 功能
                            // that.notifyBLECharacteristicValueChange()
                            break;
                        }
                    }
                },
                fail: function (res) {}
            })
        }, 100)
    },

    notifyBLECharacteristicValueChange: function () { // 启用低功耗蓝牙设备特征值变化时的 notify 功能

        console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能')
        wx.notifyBLECharacteristicValueChange({
            state: true,
            deviceId: that.connectedDeviceId,
            serviceId: that.ServicweId,
            characteristicId: that.notifyCharacteristicsId,
            complete(res) {
                /*用来监听手机蓝牙设备的数据变化*/
                wx.onBLECharacteristicValueChange(function (res) {
                    /**/
                    // that.balanceData += that.buf2string(res.value)
                    // that.hexstr += that.receiveData(res.value)
                    that.setData({
                        msg: 'reveive:' + that.receiveData(res.value)
                    })
                })
            },
            fail(res) {
                console.log(res, '启用低功耗蓝牙设备监听失败')

            }
        })
    },

    /*转换成需要的格式*/
    buf2string: function (buffer) {
        var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x)
        return arr.map((char, i) => {
            return String.fromCharCode(char);
        }).join('');
    },
    receiveData(buf) {
        return this.hexCharCodeToStr(this.ab2hex(buf))
    },
    /*转成二进制*/
    ab2hex: function (buffer) {
        var hexArr = Array.prototype.map.call(
            new Uint8Array(buffer),
            function (bit) {
                return ('00' + bit.toString(16)).slice(-2)
            }
        )
        return hexArr.join('')
    },
    /*转成可展会的文字*/
    hexCharCodeToStr: function (hexCharCodeStr) {
        var trimedStr = hexCharCodeStr.trim();
        var rawStr = trimedStr.substr(0, 2).toLowerCase() === '0x' ? trimedStr.substr(2) : trimedStr;
        var len = rawStr.length;
        var curCharCode;
        var resultStr = [];
        for (let i = 0; i < len; i = i + 2) {
            curCharCode = parseInt(rawStr.substr(i, 2), 16);
            resultStr.push(String.fromCharCode(curCharCode));
        }
        return resultStr.join('');
    },

    stringToBytes: function (str) {
        var array = new Uint8Array(str.length);
        for (let i = 0, l = str.length; i < l; i++) {
            array[i] = str.charCodeAt(i);
        }
        console.log("===========>", array);
        return array.buffer;
    },

    // 测试 发送 你好
    test1() {

        this.sendData("01 08 04 00 5d 62 5c 62 5b 00"); //    按住Alt键,输入50403（你）
        this.sendData("01 08 00 00 00 00 00 00 00 00"); // 释放Alt键
        // this.sendData("01 08 00 00 00 00 00 00 00 00"); // 释放Alt键
        // this.sendData("01 08 04 00 5c 5d 5a 59 5f 00"); // 按住Alt键,输入45217（啊）
        this.sendData("01 08 04 00 5c 5f 60 59 00 00"); // 按住Alt键,输入47811（好）
        this.sendData("01 08 04 00 00 00 00 00 00 00"); // 按住Alt键,输入47811（好）
        this.sendData("01 08 04 00 59 00 00 00 00 00"); // 按住Alt键,输入47811（好）
        this.sendData("01 08 00 00 00 00 00 00 00 00"); // 释放Alt键



        // 想发送数字的指令交给原生的K:50403，结果：不行，按下数字之前Atl会被抬起，达不到组合键的目的
        // let str = 'K:50403';
        // this.sendData("01 08 04 00 00 00 00 00 00 00"); // 按下Alt键    
        // this.blesend(this.stringToBytes(str));
        // setTimeout(() => {
        //     this.sendData("01 08 00 00 00 00 00 00 00 00"); // 释放Alt键
        // }, 500)
        // this.sendData("01 08 04 00 5d 62 5c 62 5b 00"); // 按住Alt键,输入50403（你）
        // this.sendData("01 08 04 00 00 00 00 00 00 00"); // 按住Alt键,输入50403（你）
        // this.sendData("01 08 00 00 00 00 00 00 00 00"); // 释放Alt键

        // this.sendData("01 08 04 00 5d 00 00 00 00 00"); // 按住Alt键,输入 5      
        // this.sendData("01 08 04 00 00 00 00 00 00 00"); // 按住Alt键,释放数字键
        // this.sendData("01 08 04 00 62 00 00 00 00 00"); // 按住Alt键,输入 0
        // this.sendData("01 08 04 00 00 00 00 00 00 00"); // 按住Alt键,释放数字键
        // this.sendData("01 08 04 00 5c 00 00 00 00 00"); // 按住Alt键,输入 4
        // this.sendData("01 08 04 00 00 00 00 00 00 00"); // 按住Alt键,释放数字键
        // this.sendData("01 08 04 00 62 00 00 00 00 00"); // 按住Alt键,输入 0
        // this.sendData("01 08 04 00 00 00 00 00 00 00"); // 按住Alt键,释放数字键
        // this.sendData("01 08 04 00 5b 00 00 00 00 00"); // 按住Alt键,输入 3
        // this.sendData("01 08 00 00 00 00 00 00 00 00"); // 释放Alt键
    },

    // 原本发送的方法，只能发送英文和数字
    bindViewScmd: function () {
        Notify({
            type: 'success',
            message: '发送成功 √',
            // 显示时长
            duration: this.data.notify_duration,
        });


        // 拼接上特定的字符串K:
        // let str = 'K:' + that.data.textValue;
        // this.blesend(this.stringToBytes(str));
    },
    // 发送英文小写或者数字
    sendEnglishAndNumbs(num) {
        let array = new Uint8Array(3);
        array[0] = 75;
        array[1] = 58;
        array[2] = num;
        this.blesend(array.buffer);
    },
    /**
     * 发送一个简单的中文字符 只能是GBK编码相邻数字不重复的字符 比如（50403）你
     * @param {整数} nums 
     */
    sendSimple(nums) {
        let array = new Uint8Array(10);
        let str = nums.toString();
        array[0] = 1; // 代表 键盘
        array[1] = 8; // 代表 发送8个字节
        array[2] = 4; // 代表 按下Alt键
        // array[3] = 0; // 0保留字，无意义
        for (let i = 0; i < str.length; i++) {
            // 取出对应数字的HID编码
            array[4 + i] = this.data.Alist[str.charCodeAt(i) - 48];
        }
        this.blesend(array.buffer);
        this.blesend(this.sendNull());
    },

    /**
     * 处理不同类型的汉字字符,先判断是不是简单的中文字符（GBK编码数字 相邻的数字都不相同的字符），其余的当普通汉字字符处理
     * @param {整数} num 
     */
    choiceSend(num) {
        let str = num.toString();
        for (let i = 0; i < str.length; i++) {
            if (i != 0 && str[i] == str[i - 1]) {
                console.log("发送普通汉字");
                this.sendNumberArray(num);
                return -1;
            }
        }
        console.log("发送简单汉字");
        this.sendSimple(num);
    },

    // 发送单独一个字符（无论是什么字符都可以）
    /**
     * 
     * @param {整数} num  
     */
    sendNumberArray(num) {
        let array = num.toString();
        // 实际要发送的字节码
        let char;
        // 发送指令：按住Alt键，并且按住对应数字的键
        let arr = new Uint8Array(6);
        // 发送指令：按住Alt键，并且抬起所有普通键
        let arr1 = new Uint8Array(6);
        // 发送指令：抬起所有普通键
        let arr2 = new Uint8Array(6);
        // 其余为0
        arr1[0] = 1; // 代表 键盘
        arr1[1] = 8; // 代表 发送8个字节
        arr1[2] = 4; // 代表 按下Alt键
        // 其余为0
        arr2[0] = 1; // 代表 键盘
        arr2[1] = 8; // 代表 发送8个字节

        arr[0] = 1; // 代表 键盘
        arr[1] = 8; // 代表 发送8个字节
        arr[2] = 4; // 代表 按下Alt键
        arr[3] = 0; // 0保留字，无意义
        // 仅仅需要改下标为4的元素
        for (let i = 0; i < array.length; i++) {
            char = array.charCodeAt(i) - 48; // 例如把 '50403' 转换成 [5,0,4,0,3]
            arr[4] = this.data.Alist[char];
            // 如果是连续相同的数字需要发送一个键盘抬起的指令
            if (i != 0 && array.charCodeAt(i) === array.charCodeAt(i - 1)) {
                this.blesend(arr1.buffer);
            }
            this.blesend(arr.buffer); // 按下这个数字的对应HID键盘
        }
        this.blesend(arr1.buffer);
        this.blesend(arr2.buffer);
    },

    /**
     *  筛选出字符，不同的字符分发给不同的方法，用于提供效率，效率从大到小 sendEnglishAndNumbs > sendSimple > sendNumberArray
     * @param {整数数组} arrays 
     */
    screenStr(arrays) {

        for (let i = 0; i < arrays.length; i++) {
            if (isNaN(arrays[i])) {
                // 遇到不是GBK编码的文字 直接退出
                Notify({
                    type: 'danger',
                    message: '发送失败！',
                    // 显示时长
                    duration: this.data.notify_duration,
                });
                this.setData({
                    msg:'请检查输入的文字(只能发送中英文和数字)!'
                })
                return -1;
            }
        }
        Notify({
            type: 'success',
            message: '发送成功 √',
            // 显示时长
            duration: this.data.notify_duration,
        });
        for (let i = 0; i < arrays.length; i++) {
            
            // 数字和小写字母   k-j < 13是因为长度限制只能发12个字符
            if (arrays[i] >= 48 && arrays[i] <= 57 || arrays[i] >= 97 && arrays[i] <= 122) {
                this.sendEnglishAndNumbs(arrays[i]);
            } else {
                // 否则当汉字处理
                this.choiceSend(arrays[i]);
            }
        }
    },

    // 发送
    sendch() {
        let str = this.data.textValue;
        if (str === '' || str.length == 0) {
            Notify({
                type: 'warning',
                message: '发送失败：您输入的字符串为空!',
                // 显示时长
                duration: this.data.notify_duration,
            });
            this.setData({
                msg:'发送失败'
            })
        } else {

            // 返回一个整数数组 ArrayBuffer
            let ArrayBuffer = gbk.hexStringToBuff(str);
            console.log("对应GBK编码：", ArrayBuffer);
            this.screenStr(ArrayBuffer);
        }

    },
    // # 发送 按住Alt键 且 松开所有普通键
    sendNull() {
        let arr = new Uint8Array(10);
        arr[0] = 1; // 代表 键盘
        arr[1] = 8; // 代表 发送8个字节
        return arr.buffer;
    },

    blesend: function (dataBuffer) {
        // console.log('发送的数据：', dataBuffer)
        wx.writeBLECharacteristicValue({
            deviceId: that.connectedDeviceId,
            serviceId: that.ServicweId,
            characteristicId: that.writeCharacteristicsId,
            value: dataBuffer,
            success: function (res) {
                that.setData({
                    status: '操作成功',
                    msg: '发送成功'
                })
                console.log("发送成功的数据---》：", dataBuffer);
                return 1;
            },
            fail: function (res) {
                console.log(res, 'BLE发送失败：')
                that.setData({
                    status: '蓝牙未连接',
                    msg: '发送失败',
                    connectedDeviceId: ''
                })
                console.log("发送失败的数据---》：", dataBuffer);
                return 0;
            },
            complete: function (res) {
                // console.log('BLE发送结束')
            }
        })
    },
    //str 发送数据信息
    sendData: function (hexstr) {

        hexstr = hexstr.replace(/(^\s+)|(\s+$)/g, ""); // 去除字符串两边的空白字符
        hexstr = hexstr.replace(/\s/g, ""); // 替换换字符串中所有的空字符串（也就是空格）
        if (hexstr.length == 0) return; //判断空字符串处理
        /*
        let dataBuffer = new ArrayBuffer(str.length/2)
        let dataView = new DataView(dataBuffer)
        for (let i = 0; i < str.length/2; i++) {
          dataView.setUint8(i, str.charAt(i).charCodeAt())
        }
        let dataHex = that.ab2hex(dataBuffer);
        this.writeDatas = that.hexCharCodeToStr(dataHex);
        */
        let dataBuffer = new Int8Array(util.Str2Bytes(hexstr)).buffer;
        that.blesend(dataBuffer);
    },


    //第一字节01代表键盘 第二字节代表数据长度8字节  第三字节开始是HID数据（键盘是8字节）
    bindViewSend: function () {
        that.sendData("01 08 00 00 00 00 00 00 00 00");
        that.sendData("01 08 00 00 00 00 00 00 00 00");
    },
    bindViewPrepage: function () {
        that.sendData("01 08 00 00 4B 00 00 00 00 00");
        that.sendData("01 08 00 00 00 00 00 00 00 00");
    },
    bindViewNextpage: function () {
        that.sendData("01 08 00 00 43 00 00 00 00 00");
        that.sendData("01 08 00 00 00 00 00 00 00 00");
    },
    bindViewEnter: function () {
        that.sendData("01 08 00 00 28 00 00 00 00 00");
        that.sendData("01 08 00 00 00 00 00 00 00 00");
    },

    bindViewEsc: function () {
        that.sendData("01 08 00 00 29 00 00 00 00 00");
        that.sendData("01 08 00 00 00 00 00 00 00 00");
    },
    // 断开设备连接
    closeConnect: function () {
        if (that.connectedDeviceId) {
            this.setData({
                connectedDeviceId: ''
            });
            wx.closeBLEConnection({
                deviceId: that.connectedDeviceId,
                success: function (res) {
                    that.closeBluetoothAdapter()
                },
                fail(res) {}
            })
        } else {
            //that.closeBluetoothAdapter()
        }
    },
    // 关闭蓝牙模块
    closeBluetoothAdapter: function () {
        wx.closeBluetoothAdapter({
            success: function (res) {},
            fail: function (err) {}
        })
    },


})